#include <gdk/gdkwindow.h>
#include <gdk/gdktypes.h>
#include "gdkprivate-wayland.h"
+#include "gdkseat-wayland.h"
#include "gdkwayland.h"
#include "gdkkeysyms.h"
#include "gdkdeviceprivate.h"
#include "gdkdevicemanagerprivate.h"
+#include "gdkseatprivate.h"
#include "pointer-gestures-unstable-v1-client-protocol.h"
#include <xkbcommon/xkbcommon.h>
guint initial_touch : 1;
};
-struct _GdkWaylandDeviceData
+struct _GdkWaylandSeat
{
+ GdkSeat parent_instance;
+
guint32 id;
struct wl_seat *wl_seat;
struct wl_pointer *wl_pointer;
gdouble gesture_scale;
};
+G_DEFINE_TYPE (GdkWaylandSeat, gdk_wayland_seat, GDK_TYPE_SEAT)
+
struct _GdkWaylandDevice
{
GdkDevice parent_instance;
event->crossing.detail = GDK_NOTIFY_NONLINEAR;
gdk_event_set_device (event, device);
gdk_event_set_source_device (event, device);
+ gdk_event_set_seat (event, gdk_device_get_seat (device));
gdk_window_get_device_position_double (window, device,
&event->crossing.x, &event->crossing.y,
event->crossing.detail = GDK_NOTIFY_NONLINEAR;
gdk_event_set_device (event, device);
gdk_event_set_source_device (event, source);
+ gdk_event_set_seat (event, gdk_device_get_seat (device));
event->crossing.x = touch->x;
event->crossing.y = touch->y;
event->focus_change.in = focus_in;
gdk_event_set_device (event, device);
gdk_event_set_source_device (event, device);
+ gdk_event_set_seat (event, gdk_device_get_seat (device));
_gdk_wayland_display_deliver_event (gdk_window_get_display (window), event);
}
event->crossing.window = g_object_ref (device->pointer_focus);
gdk_event_set_device (event, device->master_pointer);
gdk_event_set_source_device (event, device->pointer);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_pointer));
event->crossing.subwindow = NULL;
event->crossing.time = (guint32)(g_get_monotonic_time () / 1000);
event->crossing.mode = GDK_CROSSING_NORMAL;
event->crossing.window = g_object_ref (device->pointer_focus);
gdk_event_set_device (event, device->master_pointer);
gdk_event_set_source_device (event, device->pointer);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_pointer));
event->crossing.subwindow = NULL;
event->crossing.time = (guint32)(g_get_monotonic_time () / 1000);
event->crossing.mode = GDK_CROSSING_NORMAL;
event->motion.window = g_object_ref (device->pointer_focus);
gdk_event_set_device (event, device->master_pointer);
gdk_event_set_source_device (event, device->pointer);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_pointer));
event->motion.time = time;
event->motion.axes = NULL;
event->motion.state = device->button_modifiers | device->key_modifiers;
event->button.window = g_object_ref (device->pointer_focus);
gdk_event_set_device (event, device->master_pointer);
gdk_event_set_source_device (event, device->pointer);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_pointer));
event->button.time = time;
event->button.axes = NULL;
event->button.state = device->button_modifiers | device->key_modifiers;
event->scroll.window = g_object_ref (device->pointer_focus);
gdk_event_set_device (event, device->master_pointer);
gdk_event_set_source_device (event, device->pointer);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_pointer));
event->scroll.time = time;
event->scroll.direction = GDK_SCROLL_SMOOTH;
event->scroll.delta_x = delta_x;
event->focus_change.in = TRUE;
gdk_event_set_device (event, device->master_keyboard);
gdk_event_set_source_device (event, device->keyboard);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_pointer));
GDK_NOTE (EVENTS,
g_message ("focus in, device %p surface %p",
event->focus_change.in = FALSE;
gdk_event_set_device (event, device->master_keyboard);
gdk_event_set_source_device (event, device->keyboard);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_keyboard));
g_object_unref (device->keyboard_focus);
device->keyboard_focus = NULL;
event->key.window = device->keyboard_focus ? g_object_ref (device->keyboard_focus) : NULL;
gdk_event_set_device (event, device->master_keyboard);
gdk_event_set_source_device (event, device->keyboard);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_keyboard));
event->key.time = time_;
event->key.state = device->button_modifiers | device->key_modifiers;
event->key.group = 0;
event->touch.window = g_object_ref (touch->window);
gdk_event_set_device (event, device->touch_master);
gdk_event_set_source_device (event, device->touch);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->touch_master));
event->touch.time = time;
event->touch.state = device->button_modifiers | device->key_modifiers;
gdk_event_set_screen (event, display->screen);
event->touchpad_swipe.window = g_object_ref (device->pointer_focus);
gdk_event_set_device (event, device->master_pointer);
gdk_event_set_source_device (event, device->pointer);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_pointer));
event->touchpad_swipe.time = _time;
event->touchpad_swipe.state = device->button_modifiers | device->key_modifiers;
gdk_event_set_screen (event, display->screen);
event->touchpad_pinch.window = g_object_ref (device->pointer_focus);
gdk_event_set_device (event, device->master_pointer);
gdk_event_set_source_device (event, device->pointer);
+ gdk_event_set_seat (event, gdk_device_get_seat (device->master_pointer));
event->touchpad_pinch.time = _time;
event->touchpad_pinch.state = device->button_modifiers | device->key_modifiers;
gdk_event_set_screen (event, display->screen);
"has-cursor", TRUE,
"display", device->display,
"device-manager", device->device_manager,
+ "seat", device,
NULL);
_gdk_device_set_associated_device (device->pointer, device->master_pointer);
GDK_WAYLAND_DEVICE (device->pointer)->device = device;
"has-cursor", FALSE,
"display", device->display,
"device-manager", device->device_manager,
+ "seat", device,
NULL);
_gdk_device_set_associated_device (device->keyboard, device->master_keyboard);
GDK_WAYLAND_DEVICE (device->keyboard)->device = device;
"has-cursor", TRUE,
"display", device->display,
"device-manager", device->device_manager,
+ "seat", device,
NULL);
GDK_WAYLAND_DEVICE (device->touch_master)->device = device;
_gdk_device_set_associated_device (device->touch_master, device->master_keyboard);
"has-cursor", FALSE,
"display", device->display,
"device-manager", device->device_manager,
+ "seat", device,
NULL);
_gdk_device_set_associated_device (device->touch, device->touch_master);
GDK_WAYLAND_DEVICE (device->touch)->device = device;
"has-cursor", TRUE,
"display", device->display,
"device-manager", device_manager,
+ "seat", device,
NULL);
GDK_WAYLAND_DEVICE (device->master_pointer)->device = device;
"has-cursor", FALSE,
"display", device->display,
"device-manager", device_manager,
+ "seat", device,
NULL);
GDK_WAYLAND_DEVICE (device->master_keyboard)->device = device;
return gdk_window_new (gdk_screen_get_root_window (screen), &attrs, mask);
}
+static void
+gdk_wayland_seat_finalize (GObject *object)
+{
+ GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (object);
+
+ seat_handle_capabilities (seat, seat->wl_seat, 0);
+ g_object_unref (seat->keymap);
+ wl_surface_destroy (seat->pointer_surface);
+ /* FIXME: destroy data_device */
+ g_clear_object (&seat->keyboard_settings);
+ g_clear_object (&seat->drop_context);
+ g_hash_table_destroy (seat->touches);
+ gdk_window_destroy (seat->foreign_dnd_window);
+ stop_key_repeat (seat);
+
+ G_OBJECT_CLASS (gdk_wayland_seat_parent_class)->finalize (object);
+}
+
+static GdkSeatCapabilities
+gdk_wayland_seat_get_capabilities (GdkSeat *seat)
+{
+ GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
+ GdkSeatCapabilities caps = 0;
+
+ if (wayland_seat->master_pointer)
+ caps |= GDK_SEAT_CAPABILITY_POINTER;
+ if (wayland_seat->master_keyboard)
+ caps |= GDK_SEAT_CAPABILITY_KEYBOARD;
+ if (wayland_seat->touch_master)
+ caps |= GDK_SEAT_CAPABILITY_TOUCH;
+
+ return caps;
+}
+
+static GdkGrabStatus
+gdk_wayland_seat_grab (GdkSeat *seat,
+ GdkWindow *window,
+ GdkSeatCapabilities capabilities,
+ gboolean owner_events,
+ GdkCursor *cursor,
+ const GdkEvent *event,
+ GdkSeatGrabPrepareFunc prepare_func,
+ gpointer prepare_func_data)
+{
+ GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
+ guint32 evtime = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME;
+ GdkDisplay *display = gdk_seat_get_display (seat);
+ GdkWindow *native;
+
+ native = gdk_window_get_toplevel (window);
+
+ while (native->window_type == GDK_WINDOW_OFFSCREEN)
+ {
+ native = gdk_offscreen_window_get_embedder (native);
+
+ if (native == NULL ||
+ (!_gdk_window_has_impl (native) &&
+ !gdk_window_is_viewable (native)))
+ return GDK_GRAB_NOT_VIEWABLE;
+
+ native = gdk_window_get_toplevel (native);
+ }
+
+ if (native == NULL || GDK_WINDOW_DESTROYED (native))
+ return GDK_GRAB_NOT_VIEWABLE;
+
+ wayland_seat->pointer_grab_window = window;
+ wayland_seat->pointer_grab_time = evtime;
+ _gdk_wayland_window_set_grab_seat (window, seat);
+
+ if (prepare_func)
+ (prepare_func) (seat, window, prepare_func_data);
+
+ if (!gdk_window_is_visible (window))
+ {
+ _gdk_wayland_window_set_grab_seat (window, NULL);
+ g_critical ("Window %p has not been made visible in GdkSeatGrabPrepareFunc",
+ window);
+ return GDK_GRAB_NOT_VIEWABLE;
+ }
+
+ if (capabilities & GDK_SEAT_CAPABILITY_POINTER)
+ {
+ GdkWindow *prev_focus = gdk_wayland_device_get_focus (wayland_seat->master_pointer);
+
+ if (prev_focus != window)
+ device_emit_grab_crossing (wayland_seat->master_pointer, prev_focus,
+ window, GDK_CROSSING_GRAB, evtime);
+
+ _gdk_display_add_device_grab (display,
+ wayland_seat->master_pointer,
+ window,
+ native,
+ GDK_OWNERSHIP_NONE,
+ owner_events,
+ GDK_ALL_EVENTS_MASK,
+ _gdk_display_get_next_serial (display),
+ evtime,
+ FALSE);
+
+ g_set_object (&wayland_seat->cursor, cursor);
+ gdk_wayland_device_update_window_cursor (wayland_seat);
+ }
+
+ if (capabilities & GDK_SEAT_CAPABILITY_TOUCH)
+ {
+ GdkWindow *prev_focus = gdk_wayland_device_get_focus (wayland_seat->touch_master);
+
+ if (prev_focus != window)
+ device_emit_grab_crossing (wayland_seat->touch_master, prev_focus,
+ window, GDK_CROSSING_GRAB, evtime);
+
+ _gdk_display_add_device_grab (display,
+ wayland_seat->touch_master,
+ window,
+ native,
+ GDK_OWNERSHIP_NONE,
+ owner_events,
+ GDK_ALL_EVENTS_MASK,
+ _gdk_display_get_next_serial (display),
+ evtime,
+ FALSE);
+ }
+
+ if (capabilities & GDK_SEAT_CAPABILITY_KEYBOARD)
+ {
+ GdkWindow *prev_focus = gdk_wayland_device_get_focus (wayland_seat->master_keyboard);
+
+ if (prev_focus != window)
+ device_emit_grab_crossing (wayland_seat->master_keyboard, prev_focus,
+ window, GDK_CROSSING_GRAB, evtime);
+
+ _gdk_display_add_device_grab (display,
+ wayland_seat->master_keyboard,
+ window,
+ native,
+ GDK_OWNERSHIP_NONE,
+ owner_events,
+ GDK_ALL_EVENTS_MASK,
+ _gdk_display_get_next_serial (display),
+ evtime,
+ FALSE);
+ }
+
+ return GDK_GRAB_SUCCESS;
+}
+
+static void
+gdk_wayland_seat_ungrab (GdkSeat *seat)
+{
+ GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
+ GdkDisplay *display = gdk_seat_get_display (seat);;
+ GdkDeviceGrabInfo *grab;
+
+ if (wayland_seat->master_pointer)
+ {
+ GdkWindow *focus, *prev_focus = NULL;
+
+ grab = _gdk_display_get_last_device_grab (display, wayland_seat->master_pointer);
+
+ if (grab)
+ {
+ grab->serial_end = grab->serial_start;
+ prev_focus = grab->window;
+ }
+
+ focus = gdk_wayland_device_get_focus (wayland_seat->master_pointer);
+
+ if (focus != prev_focus)
+ device_emit_grab_crossing (wayland_seat->master_pointer, prev_focus,
+ focus, GDK_CROSSING_UNGRAB,
+ GDK_CURRENT_TIME);
+
+ gdk_wayland_device_update_window_cursor (wayland_seat);
+ }
+
+ if (wayland_seat->master_keyboard)
+ {
+ grab = _gdk_display_get_last_device_grab (display, wayland_seat->master_keyboard);
+
+ if (grab)
+ grab->serial_end = grab->serial_start;
+ }
+
+ if (wayland_seat->touch_master)
+ {
+ grab = _gdk_display_get_last_device_grab (display, wayland_seat->touch_master);
+
+ if (grab)
+ grab->serial_end = grab->serial_start;
+ }
+
+ if (wayland_seat->pointer_grab_window)
+ {
+ _gdk_wayland_window_set_grab_seat (wayland_seat->pointer_grab_window,
+ NULL);
+ wayland_seat->pointer_grab_window = NULL;
+ }
+}
+
+static GdkDevice *
+gdk_wayland_seat_get_master (GdkSeat *seat,
+ GdkSeatCapabilities capabilities)
+{
+ GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
+
+ if (capabilities == GDK_SEAT_CAPABILITY_POINTER)
+ return wayland_seat->master_pointer;
+ else if (capabilities == GDK_SEAT_CAPABILITY_KEYBOARD)
+ return wayland_seat->master_keyboard;
+ else if (capabilities == GDK_SEAT_CAPABILITY_TOUCH)
+ return wayland_seat->touch_master;
+
+ return NULL;
+}
+
+static GList *
+gdk_wayland_seat_get_slaves (GdkSeat *seat,
+ GdkSeatCapabilities capabilities)
+{
+ GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
+ GList *slaves = NULL;
+
+ if (capabilities & GDK_SEAT_CAPABILITY_POINTER)
+ slaves = g_list_prepend (slaves, wayland_seat->pointer);
+ if (capabilities & GDK_SEAT_CAPABILITY_KEYBOARD)
+ slaves = g_list_prepend (slaves, wayland_seat->keyboard);
+ if (capabilities & GDK_SEAT_CAPABILITY_TOUCH)
+ slaves = g_list_prepend (slaves, wayland_seat->touch);
+
+ return slaves;
+}
+
+static void
+gdk_wayland_seat_class_init (GdkWaylandSeatClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdkSeatClass *seat_class = GDK_SEAT_CLASS (klass);
+
+ object_class->finalize = gdk_wayland_seat_finalize;
+
+ seat_class->get_capabilities = gdk_wayland_seat_get_capabilities;
+ seat_class->grab = gdk_wayland_seat_grab;
+ seat_class->ungrab = gdk_wayland_seat_ungrab;
+ seat_class->get_master = gdk_wayland_seat_get_master;
+ seat_class->get_slaves = gdk_wayland_seat_get_slaves;
+}
+
+static void
+gdk_wayland_seat_init (GdkWaylandSeat *seat)
+{
+}
+
void
_gdk_wayland_device_manager_add_seat (GdkDeviceManager *device_manager,
guint32 id,
{
GdkDisplay *display;
GdkWaylandDisplay *display_wayland;
- GdkWaylandDeviceData *device;
+ GdkWaylandSeat *seat;
display = gdk_device_manager_get_display (device_manager);
display_wayland = GDK_WAYLAND_DISPLAY (display);
- device = g_new0 (GdkWaylandDeviceData, 1);
- device->id = id;
- device->keymap = _gdk_wayland_keymap_new ();
- device->display = display;
- device->device_manager = device_manager;
- device->touches = g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify) g_free);
- device->foreign_dnd_window = create_foreign_dnd_window (display);
- device->wl_seat = wl_seat;
+ seat = g_object_new (GDK_TYPE_WAYLAND_SEAT,
+ "display", display,
+ NULL);
+ seat->id = id;
+ seat->keymap = _gdk_wayland_keymap_new ();
+ seat->display = display;
+ seat->device_manager = device_manager;
+ seat->touches = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) g_free);
+ seat->foreign_dnd_window = create_foreign_dnd_window (display);
+ seat->wl_seat = wl_seat;
- device->pending_selection = GDK_NONE;
+ seat->pending_selection = GDK_NONE;
- wl_seat_add_listener (device->wl_seat, &seat_listener, device);
- wl_seat_set_user_data (device->wl_seat, device);
+ wl_seat_add_listener (seat->wl_seat, &seat_listener, seat);
+ wl_seat_set_user_data (seat->wl_seat, seat);
- device->data_device =
+ seat->data_device =
wl_data_device_manager_get_data_device (display_wayland->data_device_manager,
- device->wl_seat);
- device->drop_context = _gdk_wayland_drop_context_new (device->data_device);
- wl_data_device_add_listener (device->data_device,
- &data_device_listener, device);
+ seat->wl_seat);
+ seat->drop_context = _gdk_wayland_drop_context_new (seat->data_device);
+ wl_data_device_add_listener (seat->data_device,
+ &data_device_listener, seat);
- device->current_output_scale = 1;
- device->pointer_surface =
+ seat->current_output_scale = 1;
+ seat->pointer_surface =
wl_compositor_create_surface (display_wayland->compositor);
- wl_surface_add_listener (device->pointer_surface,
+ wl_surface_add_listener (seat->pointer_surface,
&pointer_surface_listener,
- device);
+ seat);
+
+ init_devices (seat);
- init_devices (device);
+ gdk_display_add_seat (display, GDK_SEAT (seat));
}
void
_gdk_wayland_device_manager_remove_seat (GdkDeviceManager *manager,
guint32 id)
{
- GdkWaylandDeviceManager *device_manager = GDK_WAYLAND_DEVICE_MANAGER (manager);
+ GdkDisplay *display = gdk_device_manager_get_display (manager);
GList *l;
- for (l = device_manager->devices; l != NULL; l = l->next)
+ l = gdk_display_list_seats (display);
+
+ while (l)
{
- GdkWaylandDevice *wayland_device = l->data;
- GdkWaylandDeviceData *device = wayland_device->device;
+ GdkWaylandSeat *seat = l->data;
- if (device->id == id)
- {
- seat_handle_capabilities (device, device->wl_seat, 0);
- g_object_unref (device->keymap);
- wl_surface_destroy (device->pointer_surface);
- /* FIXME: destroy data_device */
- g_clear_object (&device->keyboard_settings);
- g_clear_object (&device->drop_context);
- g_hash_table_destroy (device->touches);
- gdk_window_destroy (device->foreign_dnd_window);
- stop_key_repeat (device);
- g_free (device);
+ if (seat->id != id)
+ continue;
- break;
- }
+ gdk_display_remove_seat (display, GDK_SEAT (seat));
+ break;
}
}
device->button_modifiers = 0;
gdk_event_set_device (event, gdk_device);
gdk_event_set_source_device (event, gdk_device);
+ gdk_event_set_seat (event, gdk_device_get_seat (gdk_device));
_gdk_wayland_display_deliver_event (gdk_device_get_display (gdk_device), event);
}
+
+struct wl_seat *
+gdk_wayland_seat_get_wl_seat (GdkSeat *seat)
+{
+ g_return_val_if_fail (GDK_IS_WAYLAND_SEAT (seat), NULL);
+
+ return GDK_WAYLAND_SEAT (seat)->wl_seat;
+}